// 代码参考：https://oshwhub.com/shukkkk/esp32s3_tft_mp3
#include <Arduino.h>
#include <Adafruit_NeoPixel.h>
#include <WiFi.h>
#include "time.h"

#include "global_config.h"
#include <ArduinoWebsockets.h>
#include <ArduinoJson.h>

#include "SPI.h"
#include <HTTPClient.h>

#include <UrlEncode.h>

#include <esp_system.h>
#include "bsp_i2s.h"

#include "bsp_ntp.h"
#include "app_xf.h"

#if 0
#include "app_baidu_authen.h"
#include "app_bd_tts.h"
#endif


// 录音缓存区
extern int16_t audioData[2560];
extern int16_t *pcm_data; 
extern uint recordingSize;

//录音ASR结果
extern String g_stt_text;
extern bool g_stt_ste;


#if 0
//预备TTS的输入
extern String g_encodedText;
#endif


//LED等
Adafruit_NeoPixel pixels(PIX_NUM, PIN_PIXS, NEO_GRB + NEO_KHZ800);

//网络相关
extern WiFiUDP ntpUDP;
extern NTPClient timeClient;

using namespace websockets;
WebsocketsClient client;    //WebSocket 客户端

void setup()
{
  //0. 初始化串口
  Serial.begin(115200);

  uint8_t c = 10, d = 250;  
  uint8_t result2 = c - d;
  Serial.print("10 - 250 = ");
  Serial.println(result2);  // 输出 16


  //1. LED灯？
  pinMode(48, OUTPUT);
  digitalWrite(48, HIGH);

  //2. 链接Wifi
  Serial.printf("Connecting to %s ", ssid);
  WiFi.begin(ssid, password);
  while (WiFi.status() != WL_CONNECTED)
  {
    delay(500);
    Serial.print(".");
  }
  Serial.println(" CONNECTED");

  //3. 初始化 ntp 客户端，得到日期时间
  setup_ntp_client();
  getDateTime();

  //LED灯
  pixels.begin();
  pixels.setBrightness(8);
  // 熄灭2812
  pixels.clear();
  pixels.show();

  //4. 初始化 I2S 设备 INMP441
  Serial.println("Setup I2S ...");
  i2s_install();
  i2s_setpin();
  esp_err_t err = i2s_start(I2S_PORT_0);
  if (err != ESP_OK)
  {
    Serial.printf("I2S start failed (I2S_PORT_0): %d\n", err);
    while (true)
      ;
  }
  else
  {
    Serial.printf("I2S start OK!\r\n");
  }

  // 5. 设置 Websocket 客户端的回调函数
  // run callback when messages are received 
  client.onMessage(handleWebSocketMessage);
  Serial.printf("Please hit keyboard input '1' to start Audio capturing!\r\n");

}


void loop()
{
  if (Serial.available())
  {
    // delay(20);
    if (Serial.read() == '1')
    {
      g_stt_text = "";//最终的结果
      Serial.println("Recording...");
      
      //1. 分配 pcm_data 内存，分配的大小为 (16000 * 10) * 16 bit（2B） = 320kB= 0.3125MB
      pcm_data = (int16_t *)ps_malloc(BUFFER_SIZE * sizeof(int16_t));
      if (!pcm_data)
      {
        Serial.println("Failed to allocate memory for pcm_data from PSRAM");
        return;
      }

      recordingSize = 0;
      size_t bytes_read = 0;
      // uint16_t x = 0, y = 0;


      /**
       * @brief  
       * recordingSize：采样点个数（或者说，采样得到的字节数的1/2 或者说 uint16_t 的个数(每次采样，深度为16bit，得到2字节)）
       * recordTimeSeconds：此处为3s
       * SAMPLE_RATE：此处为16k 
       * recordTimeSeconds * SAMPLE_RATE 表示i2s采集，经过3s所得到的 uint16_t 的个数 
       */
      while (recordingSize < recordTimeSeconds * SAMPLE_RATE)
      {
       // 开始循环录音，将录制结果保存在pcm_data中
        esp_err_t result = i2s_read(I2S_PORT_0, audioData, sizeof(audioData), &bytes_read, portMAX_DELAY);
        memcpy(pcm_data + recordingSize/*pcm_data 是 uint16_t 类型的指针，因此recordingSize不需要乘2*/, 
          audioData, 
          bytes_read);
        recordingSize += bytes_read / 2; //此处除以2，很有意思
      }

      Serial.printf("Total bytes read: %d\n", recordingSize);
      Serial.println("Recording complete.");
      STTsend(); // STT请求开始
      free(pcm_data);
    } 
  }
        
  if (client.available())
  {   
    client.poll();
  }

  if(g_stt_ste) //如果最终得到ASR的结果
  {
     delay(500);
     g_stt_ste = 0;

     #if 0
     //g_encodedText = "";
     //g_encodedText = urlEncode(urlEncode(g_stt_text));
     //tts_get_response(g_encodedText);
     //tts_player();
    #endif
  }

  //tts_loop();
  delay(50);
}